from PyQt4 import QtCore

class TweaksModel(QtCore.QAbstractItemModel):
	"""Application database model."""

	def __init__(self, data, parent=None):
		"""Init

		@param data application database.
		"""

		QtCore.QAbstractItemModel.__init__(self, parent)
		rootData = [QtCore.QVariant(header) for header in ("Tweak",)]
		self.rootItem = TreeItem(rootData)
		for tweak in data:
			self.rootItem.appendChild(TweakItem(tweak, self.rootItem))

	def columnCount(self, parent):
		if parent.isValid():
			return parent.internalPointer().columnCount()
		else:
			return self.rootItem.columnCount()

	def data(self, index, role):

		if not index.isValid():
			return QtCore.QVariant()

		if role == QtCore.Qt.CheckStateRole:
			if index.internalPointer().isCheckable(index):
				return QtCore.QVariant(index.internalPointer().checkState)

		if role == QtCore.Qt.DisplayRole:
			item = index.internalPointer()
			return QtCore.QVariant(item.data(index.column()))

		return QtCore.QVariant()

	def flags(self, index):

		if not index.isValid():
			return QtCore.Qt.ItemIsEnabled

		if index.internalPointer().isCheckable(index):
			return QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsUserCheckable

		return QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable

	def headerData(self, section, orientation, role):

		if orientation == QtCore.Qt.Horizontal and role == QtCore.Qt.DisplayRole:
			return self.rootItem.data(section)

		return QtCore.QVariant()

	def index(self, row, column, parent):

		if row < 0 or column < 0 or row >= self.rowCount(parent) or column >= self.columnCount(parent):
			return QtCore.QModelIndex()

		if not parent.isValid():
			parentItem = self.rootItem
		else:
			parentItem = parent.internalPointer()

		childItem = parentItem.child(row)
		if childItem:
			return self.createIndex(row, column, childItem)
		else:
			return QtCore.QModelIndex()

	def parent(self, index):

		if not index.isValid():
			return QtCore.QModelIndex()

		childItem = index.internalPointer()
		parentItem = childItem.parent()

		if parentItem == self.rootItem:
			return QtCore.QModelIndex()

		return self.createIndex(parentItem.row(), 0, parentItem)

	def rowCount(self, parent):

		if parent.column() > 0:
			return 0

		if not parent.isValid():
			parentItem = self.rootItem
		else:
			parentItem = parent.internalPointer()

		return parentItem.childCount()

	def setData(self, index, value, role=QtCore.Qt.EditRole):

		if not index.isValid():
			return False

		if role == QtCore.Qt.CheckStateRole:
			item = index.internalPointer()
			if item.isCheckable(index):
				if item.checkState == QtCore.Qt.Unchecked:
					item.checkState = QtCore.Qt.Checked
				else:
					item.checkState = QtCore.Qt.Unchecked
					
				self.emit(QtCore.SIGNAL("dataChanged(const QModelIndex&, const QModelIndex&)"), index, index)
				return True

		return False
	
	def getTweakList(self):
		'''retrieves tweak objects that are markeds as checked'''
		
		tweaks = [ ]
		for tweak in self.rootItem.childItems:
			if tweak.checkState == QtCore.Qt.Checked:
				tweaks.append(tweak.itemData)
		return tweaks
	
	def setTweakList(self, tweaks):
		'''sets selection according to provided app versions.
		
		@param tweaks tweaks to select.'''
		
		self.clearChecks()
		for tweak in tweaks:
			for tweakItem in self.rootItem.childItems:
				if tweakItem.itemData.path == tweak.path:
					tweakItem.checkState = QtCore.Qt.Checked
		self.emit(QtCore.SIGNAL("dataChanged()"))
					
		
	def clearChecks(self):
		'''clears checked state on all objects.'''
		
		for tweakItem in self.rootItem.childItems:
			tweakItem.checkState = QtCore.Qt.Unchecked
		self.emit(QtCore.SIGNAL("dataChanged()"))

class TreeItem(object):
	"""Base class for tree items."""

	def __init__(self, data, parent=None):

		self.parentItem = parent
		self.itemData = data
		self.childItems = []
		self.checkCol = -1
		self.checkState = QtCore.Qt.Unchecked

	def appendChild(self, item):

		self.childItems.append(item)

	def child(self, row):

		return self.childItems[row]

	def childCount(self):

		return len(self.childItems)

	def columnCount(self):

		return len(self.itemData)

	def data(self, column):

		return self.itemData[column]

	def parent(self):

		return self.parentItem

	def row(self):

		if self.parentItem:
			return self.parentItem.childItems.index(self)

		return 0

	def isCheckable(self, index):

		if index.column() == self.checkCol:
			return 1

		return 0
	

class TweakItem(TreeItem):
	"""Application item in a tree."""

	def __init__(self, tweak, parent=None):

		TreeItem.__init__(self, tweak, parent)
		self.checkCol = 0

	def data(self, column):
		if column == 0:
			return self.itemData.desc


	def columnCount(self):

		return 1
